package com.ruoyi.smart.service;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.smart.mqtt.MqttClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class DeviceControlService {

    private final MqttClient mqttClient;

    @Resource
    private RedisCache redisCache;

    // Redis key前缀
    private static final String CONTROL_HISTORY_KEY = "smart:device:control:history:";
    private static final int MAX_HISTORY_SIZE = 100; // 最大历史记录数

    public DeviceControlService(MqttClient mqttClient) {
        this.mqttClient = mqttClient;
    }

    /**
     * 发送单个设备控制命令
     * @param deviceId 设备ID
     * @param command 控制命令
     */
    public void sendControlCommand(String deviceId, String command) {
        String topic = "topic/device/control/" + deviceId;
        mqttClient.publish(topic, command, 1, false);
        saveControlHistory(deviceId, command);
        log.info("向设备 {} 发送控制命令: {}", deviceId, command);
    }

    /**
     * 批量发送控制命令
     * @param deviceCommands 设备命令映射 (设备ID -> 命令)
     */
    public void batchSendControlCommand(Map<String, String> deviceCommands) {
        if (deviceCommands == null || deviceCommands.isEmpty()) {
            log.warn("批量控制命令为空");
            return;
        }

        log.info("开始批量发送控制命令，设备数量: {}", deviceCommands.size());

        int successCount = 0;
        int failCount = 0;

        for (Map.Entry<String, String> entry : deviceCommands.entrySet()) {
            String deviceId = entry.getKey();
            String command = entry.getValue();

            try {
                sendControlCommand(deviceId, command);
                successCount++;
            } catch (Exception e) {
                log.error("向设备 {} 发送命令失败: {}", deviceId, e.getMessage());
                failCount++;
            }

            // 添加短暂延迟，避免对MQTT服务器造成过大压力
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        log.info("批量控制命令完成: 成功={}, 失败={}", successCount, failCount);
    }

    /**
     * 按设备类型批量发送命令
     * @param deviceType 设备类型
     * @param command 命令
     * @param deviceStatusService 设备状态服务
     */
    public void batchSendCommandByType(String deviceType, String command, DeviceStatusService deviceStatusService) {
        Map<String, Boolean> allDevices = deviceStatusService.getAllDeviceStatus();
        Map<String, String> deviceCommands = new HashMap<>();

        // 筛选指定类型的设备（这里假设设备ID包含类型信息）
        for (String deviceId : allDevices.keySet()) {
            if (deviceId.contains(deviceType)) {
                deviceCommands.put(deviceId, command);
            }
        }

        if (!deviceCommands.isEmpty()) {
            batchSendControlCommand(deviceCommands);
        } else {
            log.warn("未找到类型为 {} 的设备", deviceType);
        }
    }

    /**
     * 按状态批量发送命令
     * @param online 是否在线设备
     * @param command 命令
     * @param deviceStatusService 设备状态服务
     */
    public void batchSendCommandByStatus(boolean online, String command, DeviceStatusService deviceStatusService) {
        Map<String, Boolean> allDevices = deviceStatusService.getAllDeviceStatus();
        Map<String, String> deviceCommands = new HashMap<>();

        for (Map.Entry<String, Boolean> entry : allDevices.entrySet()) {
            if (entry.getValue() == online) {
                deviceCommands.put(entry.getKey(), command);
            }
        }

        if (!deviceCommands.isEmpty()) {
            batchSendControlCommand(deviceCommands);
        } else {
            log.warn("未找到状态为 {} 的设备", online ? "在线" : "离线");
        }
    }

    /**
     * 保存控制历史
     * @param deviceId 设备ID
     * @param command 命令
     */
    private void saveControlHistory(String deviceId, String command) {
        String historyKey = CONTROL_HISTORY_KEY + deviceId;
        ControlHistory history = new ControlHistory(deviceId, command, new Date());

        // 使用列表存储历史记录
        List<ControlHistory> historyList = redisCache.getCacheObject(historyKey);
        if (historyList == null) {
            historyList = new ArrayList<>();
        }

        // 添加新记录到开头
        historyList.add(0, history);

        // 限制历史记录数量
        if (historyList.size() > MAX_HISTORY_SIZE) {
            historyList = historyList.subList(0, MAX_HISTORY_SIZE);
        }

        // 保存到Redis，设置30天过期
        redisCache.setCacheObject(historyKey, historyList, 30, TimeUnit.DAYS);
    }

    /**
     * 获取设备控制历史
     * @param deviceId 设备ID
     * @param limit 限制条数
     * @return 控制历史列表
     */
    public List<ControlHistory> getControlHistory(String deviceId, int limit) {
        String historyKey = CONTROL_HISTORY_KEY + deviceId;
        List<ControlHistory> historyList = redisCache.getCacheObject(historyKey);

        if (historyList == null) {
            return new ArrayList<>();
        }

        // 限制返回数量
        return historyList.subList(0, Math.min(limit, historyList.size()));
    }

    /**
     * 控制历史记录类
     */
    public static class ControlHistory {
        private String deviceId;
        private String command;
        private Date timestamp;

        public ControlHistory(String deviceId, String command, Date timestamp) {
            this.deviceId = deviceId;
            this.command = command;
            this.timestamp = timestamp;
        }

        // getter 和 setter 方法
        public String getDeviceId() {
            return deviceId;
        }

        public void setDeviceId(String deviceId) {
            this.deviceId = deviceId;
        }

        public String getCommand() {
            return command;
        }

        public void setCommand(String command) {
            this.command = command;
        }

        public Date getTimestamp() {
            return timestamp;
        }

        public void setTimestamp(Date timestamp) {
            this.timestamp = timestamp;
        }
    }
}
